Интерактивный мячик, подчиняющийся законам физики

Возьмите мышкой за мячик и киньте его в любую сторону.



В этой статье мы продолжаем знакомим вас с возможностями JavaScript библиотеки KineticJS. В данном случае используется симулятор физической среды. Как мы можем видеть, мячик подчиняется силе гравитации, так-же он отскакивает от поверхностей при ударе и движется по правильным траекториям. Сие благолепие достигается применением JavaScript библиотеки kinetic-v3.4.0. Мы с радостью представим вам код, позволяющий все это осуществить.

Давайте присоединим библиотеку

CODE:

<script src="http://www.html5canvastutorials.com/libraries/kinetic-v3.4.0.js"> </script>







Теперь, между тегами <script></script> пропишем следующий код:

CODE:


window.requestAnimFrame = (function(callback){
            return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(callback){
                window.setTimeout(callback, 1000 / 60);
            };
        })();
 
        function animate(lastTime, stage, ball, dd){
            var date = new Date();
            var time = date.getTime();
            var timeDiff = time - lastTime;
 
            // update
            updateBall(timeDiff, stage, ball, dd);
 
            // draw
            stage.drawActors();
 
            // request new frame
            requestAnimFrame(function(){
                animate(time, stage, ball, dd);
            });
        }
 
        window.onload = function(){
            var stage = new Kinetic.Stage("container", 578, 200);
            var canvas = stage.getCanvas();
            var context = stage.getContext();
            var radius = 20;
 
            var ball = new Kinetic.Shape(function(){
                var context = this.getContext();
                context.beginPath();
                context.arc(0, 0, radius, 0, 2 * Math.PI, false);
                context.fillStyle = "red";
                context.fill();
            });
 
            // add custom properties
            ball.vx = 0;
            ball.vy = 0;
            ball.radius = radius;
 
            ball.on("mousedown", function(){
                var mousePos = stage.getMousePos();
                var mouseX = mousePos.x;
                var mouseY = mousePos.y;
                dd.isDragging = true;
                dd.offsetX = mouseX - ball.x;
                dd.offsetY = mouseY - ball.y;
                ball.vx = 0;
                ball.vy = 0;
            });
 
            ball.on("mouseover", function(){
                document.body.style.cursor = "pointer";
            });
 
            ball.on("mouseout", function(){
                document.body.style.cursor = "default";
            });
 
            ball.x = canvas.width / 2;
            ball.y = canvas.height / 2;
 
            // add ball to stage
            stage.add(ball);
 
            // globals needed for drag and drop
            var dd = {
                mouseX: 0,
                mouseY: 0,
                mouseOffsetX: 0,
                mouseOffsetY: 0,
                lastMouseX: 0,
                lastMouseY: 0,
                offsetX: 0,
                offsetY: 0,
                isDragging: false
            };
 
            stage.on("mouseup", function(){
                dd.isDragging = false;
                dd.mouseOffsetX = 0;
                dd.mouseOffsetY = 0;
            }, false);
 
            var date = new Date();
            var time = date.getTime();
            animate(time, stage, ball, dd);
        };
 
        function updateBall(timeDiff, stage, ball, dd){
            var canvas = stage.getCanvas();
            var ballX = ball.x;
            var ballY = ball.y;
 
            // physics variables
            var gravity = 20; // px / second^2
            var speedIncrementFromGravityEachFrame = gravity *
             timeDiff / 1000;
            var collisionDamper = 0.2; // 20% energy loss
            var floorFriction = 5; // px / second^2
            var floorFrictionSpeedReduction = floorFriction *
             timeDiff / 1000;
 
            if (dd.isDragging) {
                var mousePos = stage.getMousePos();
 
                if (mousePos !== null) {
                    var mouseX = mousePos.x;
                    var mouseY = mousePos.y;
 
                    var c = 0.06 * timeDiff;
                    ball.vx = c * (mouseX - dd.lastMouseX);
                    ball.vy = c * (mouseY - dd.lastMouseY);
                    dd.lastMouseX = mouseX;
                    dd.lastMouseY = mouseY;
                    dd.mouseOffsetX = mouseX - dd.offsetX;
                    dd.mouseOffsetY = mouseY - dd.offsetY;
                    ballX = mouseX - dd.offsetX;
                    ballY = mouseY - dd.offsetY;
                }
            }
            else {
                // gravity
                ball.vy += speedIncrementFromGravityEachFrame;
                ballX += ball.vx;
                ballY += ball.vy;
 
                // ceiling condition
                if (ballY < ball.radius) {
                    ballY = ball.radius;
                    ball.vy *= -1;
                    ball.vy *= (1 - collisionDamper);
                }
 
                // floor condition
                if (ballY > (canvas.height - ball.radius)) {
                    ballY = canvas.height - ball.radius;
                    ball.vy *= -1;
                    ball.vy *= (1 - collisionDamper);
                }
 
                // floor friction
                if (ballY == canvas.height - ball.radius) {
                    if (ball.vx > 0.1) {
                        ball.vx -= floorFrictionSpeedReduction;
                    }
                    else if (ball.vx < -0.1) {
                        ball.vx += floorFrictionSpeedReduction;
                    }
                    else {
                        ball.vx = 0;
                    }
                }
 
                // right wall condition
                if (ballX > (canvas.width - ball.radius)) {
                    ballX = canvas.width - ball.radius;
                    ball.vx *= -1;
                    ball.vx *= (1 - collisionDamper);
                }
 
                // left wall condition
                if (ballX < (ball.radius)) {
                    ballX = ball.radius;
                    ball.vx *= -1;
                    ball.vx *= (1 - collisionDamper);
                }
            }
 
            ball.x = ballX;
            ball.y = ballY;
        }

Ну, и, теперь, в теле нашего документа пропишем следующее:

CODE:

<body onmousedown="return false;">     
 <div id="container">     
 </div>  
 </body>


Оригинал статьи на английском языке: www.html5canvastutorials.com





Комментарии ВКонтакте

arrow вернуться к странице статей про HTML5 Canvas